/*
 * Copyright 2011 yura.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.opu.db_vdumper.actions;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import org.opu.db_vdumper.beans.ApplicationData;
import org.opu.db_vdumper.services.CopyDbService;
import org.opu.db_vdumper.services.ServiceFactory;
import org.opu.db_vdumper.ui.component.area.model.CanvesModel;
import org.opu.db_vdumper.ui.component.db.DbResponseViewer;
import org.opu.db_vdumper.ui.component.db.UserDataPane;
import org.opu.db_vdumper.ui.i18n.DumpActionI18N;
import org.opu.db_vdumper.ui.i18n.DumpActionI18NImpl;
import org.opu.db_vdumper.util.Logger;
import org.opu.db_vdumper.util.datacopy.DatabaseException;
import org.opu.db_vdumper.util.datacopy.DbResponse;
import org.opu.db_vdumper.util.monitors.DoubleProgresMonitorImpl;

/**
 *
 * @author yura
 */
public class Dump extends AbstractAction {

    public static final String MNAME = "Dump";
    public static final int STRUT = 16;
    private ApplicationData data;
    private DumpActionI18N i18N;

    public Dump(ApplicationData applicationData) {
        this.data = applicationData;
        this.i18N = new DumpActionI18NImpl();
    }

    @Override
    public String getName() {
        return MNAME;
    }

    @Override
    public void action(ActionEvent e) {

        final CanvesModel canvesModel = data.getCanvesModel();
        final JFrame mFrame = data.getMainView().asFrame();

        if (canvesModel == null) {
            error(null, "Now canves model", i18N.nowModel(), mFrame);
            return;
        }

        final DoubleProgresMonitorImpl monitor = new DoubleProgresMonitorImpl(
                mFrame, data.getI18N().getName());
        monitor.showLowBar(false);

        Object source = source(mFrame);
        if (source == null){
            Logger.getInstance().info(this, "Break");
            return;
        }

        ServiceFactory services = data.getServiceFactory();
        final CopyDbService cservice;
        try {
            cservice = services.getCopyDbService(data.getDbManager(), source);
        } catch (Exception ex) {
            error(ex, "Cant't init database service", i18N.cannotService(), mFrame);
            return;
        }

        final Map<String, DbResponse> map = new HashMap<String, DbResponse>();

        new Thread() {

            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getInstance().error(this, ex);
                }

                Logger.getInstance().debug(this, "Data started: " + !monitor.isCanceled());
                try {
                    map.putAll(cservice.createStructure(canvesModel, monitor));
                } catch (DatabaseException ex) {
                    error(ex, "Cant't copy database structure",
                            i18N.cannotDbStructure(), mFrame);
                }
                monitor.setVisible(false);
            }
        }.start();
        monitor.setVisible(true);

        if (map.isEmpty()) {
            flushTarge(cservice);
            return;
        }

        int i = DbResponseViewer.showDialog(mFrame, map);

        if (i == DbResponseViewer.STATUS_CONTINUE) {
            monitor.setProgress(1);
            monitor.showLowBar(true);
            monitor.reset();

            new Thread() {

                @Override
                public void run() {
                    try {
                        cservice.copyData(monitor);
                    } catch (DatabaseException ex) {
                        error(ex, "Cant't copy database data",
                                i18N.cannotDbData(), mFrame);
                    }
                    monitor.setVisible(false);
                }
            }.start();

            monitor.setVisible(true);
            flushTarge(cservice);
        }
    }

    private Object source(JFrame m) {
        final List list = new ArrayList(1);
        final JDialog dialog = new JDialog(m, m.getTitle(), true);

        JFileChooser fch = new JFileChooser();
        fch.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fch.setFileHidingEnabled(false);
        fch.setControlButtonsAreShown(false);
        fch.setMultiSelectionEnabled(false);

        UserDataPane dbp = new UserDataPane();
        dbp.getSouthPane().setVisible(false);

        JLabel lbl = new JLabel(i18N.dialogLblChose());

        final JComboBox cb = new JComboBox(new VObj[]{new VObj(i18N.dialogFile(),
                    dbp, fch), new VObj(i18N.dialogDb(), fch, dbp)});
        cb.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                VObj obj = (VObj) cb.getSelectedItem();
                obj.oldComp.setVisible(false);
                obj.newComp.setVisible(true);
            }
        });
        cb.setSelectedIndex(0);

        JButton ok = new JButton(new AbstractAction(){

            @Override
            public String getName() {
                return "Ok";
            }

            @Override
            public void action(ActionEvent e) {
                dialog.setVisible(false);
            }

        });
        JButton cancel = new JButton(new AbstractAction(){

            @Override
            public String getName() {
                return "Cancel";
            }

            @Override
            public void action(ActionEvent e) {
                list.add(new Object());
                dialog.setVisible(false);
            }

        });

        Container contentPane = dialog.getContentPane();

        Box bn = Box.createHorizontalBox();
        bn.add(Box.createGlue());
        bn.add(lbl);
        bn.add(Box.createHorizontalStrut(STRUT));
        bn.add(cb);
        bn.add(Box.createGlue());

        Box bc = Box.createHorizontalBox();
        bc.add(Box.createHorizontalStrut(STRUT));
        bc.add(fch);
        bc.add(dbp);
        bc.add(Box.createHorizontalStrut(STRUT));

        Box bs = Box.createHorizontalBox();
        bs.add(Box.createGlue());
        bs.add(cancel);
        bs.add(Box.createHorizontalStrut(STRUT));
        bs.add(ok);
        bs.add(Box.createHorizontalStrut(STRUT));

        contentPane.add(bn, BorderLayout.NORTH);
        contentPane.add(bc, BorderLayout.CENTER);
        contentPane.add(bs, BorderLayout.SOUTH);

        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);

        if (!list.isEmpty()){
            return null;
        }

        if (fch.isVisible()){
            File file = fch.getSelectedFile();
            if (file == null){
            	File dir = fch.getCurrentDirectory();
                if (dir != null){
                	file = new File(dir, "dump.sql");
                } else {
                	file = new File("dump.sql");
                }
            }
            Logger.getInstance().info(this, file.getAbsolutePath());
            return file;
        } else {
            return dbp.getData();
        }
    }

    private void flushTarge(CopyDbService cservice) {
        try {
            cservice.getTargetDatabase().close();
        } catch (DatabaseException ex) {
            Logger.getInstance().error(this, "Cant't close target database");
            Logger.getInstance().error(this, ex);
        }
    }

    private void error(Exception ex, String log, String msg, JFrame frame) {
        Logger.getInstance().error(this, log);
        if (ex != null) {
            Logger.getInstance().error(this, ex);
        }

        try {
            JOptionPane.showMessageDialog(frame, msg);
        } catch (HeadlessException hex) {
            Logger.getInstance().error(this, hex);
        }
    }

    class VObj {

        String name;
        JComponent oldComp;
        JComponent newComp;

        public VObj(String name, JComponent oldComp, JComponent newComp) {
            this.name = name;
            this.oldComp = oldComp;
            this.newComp = newComp;
        }

        @Override
        public String toString() {
            return String.valueOf(name);
        }
    }
}
